; (function () {
    return
    // =================================
    var foo1 = function () {
        console.log('foo1==');
    }
    foo1();  // foo1==
    var foo1 = function () {
        console.log('foo2==');
    }
    foo1(); // foo2==
    // 这里的变量其实有提升
    // 不过问题不大,不影响
    // =================================




    function foo() {
        console.log('foo1');
    }
    foo();  // foo2
    function foo() {
        console.log('foo2');
    }
    foo(); // foo2
    // 这里的函数提升了,导致问题
    // =================================

})();

// 上下文解释
; (function () {
    return
    //   这就要说到 JavaScript 的可执行代码(executable code)的类型有哪些了？
    // 其实很简单，就三种，全局代码、函数代码、eval代码。
    // 试想当 JavaScript 开始要解释执行代码的时候，最先遇到的就是全局代码，
    // 所以初始化的时候首先就会向执行上下文栈压入一个全局执行上下文，
    // 我们用 globalContext 表示它，并且只有当整个应用程序结束的时候，
    // ECStack 才会被清空，所以 ECStack 最底部永远有个 globalContext：
    let ECStack = [];
    let globalContext = '我是全局上下文'
    // 也就是 默认有一个
    ECStack = [globalContext]
    function fun3() {
        console.log('fun3')
    }
    function fun2() {
        fun3();
    }
    function fun1() {
        fun2();
    }
    fun1();


    // 当执行一个函数的时候，就会创建一个执行上下文，
    // 并且压入执行上下文栈，当函数执行完毕的时候，
    // 就会将函数的执行上下文从栈中弹出。

    // fun1()
    ECStack.push('fun1上下文');

    // fun1中竟然调用了fun2，还要创建fun2的执行上下文
    ECStack.push('fun2上下文');

    // 擦，fun2还调用了fun3！
    ECStack.push('fun3上下文');

    // fun3执行完毕
    ECStack.pop();
    // fun2执行完毕
    ECStack.pop();
    // fun1执行完毕
    ECStack.pop();

    console.log(ECStack) //[ '我是全局上下文' ]

})();

// 结合上面的原理, 思考一下面的思考题
; (function () {
    return
    let ECStack = []
    var scope = "global scope";
    function checkscope() {
        var scope = "local scope";
        function f() {
            return console.log(scope);
        }
        return f();
    }
    checkscope();

    ECStack.push('checkscope上下文');
    ECStack.push('f函数上下文');
    ECStack.pop();
    ECStack.pop();

    var scope1 = "global scope1";
    function checkscope1() {
        var scope1 = "local scope1";
        function f() {
            return console.log(scope1);
        }
        return f;
    }
    checkscope1()();

    ECStack.push('checkscope上下文');
    ECStack.pop();
    ECStack.push('f函数上下文');
    ECStack.pop();



})();

// 上下文大概发生的顺序
; (function () {
    return

    function foo(a) {
        var b = 2;
        function c() { }
        var d = function () { };

        b = 3;

    }

    foo(1);

    AO = {
        arguments: {
            0: 1,
            length: 1
        },
        a: 1,//由名称和对应值组成的一个变量对象的属性被创建
        b: undefined,//变量提升, 现在用let就不会了
        c: function c() { },// 函数提升
        d: undefined//变量提升,现在用let 就不会了
    }


})();

;(function(){
  return
  let getA = function(){
    let a = 1
    a = 2
    console.log(a)
  }
  getA() // 2

  b = 2
  let getB = function(){
    let b = 1
    
    console.log(b)
  }
  getB() // 1

  
  let getC = function(){
    c = 3 //Cannot access 'c' before initialization 初始化前无法访问C
    let c = 4 
    console.log(c)
  }
//   getC() // 报错
})();
